package com.innovation.ic.b1b.framework.manager;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

import java.util.concurrent.ExecutorService;

/**
 * zookeeper的管理类
 */
@Slf4j
public class ZookeeperManager {

    private CuratorFramework curatorFramework;
    private ExecutorService executorService;

    public ZookeeperManager(String host, int sessionTimeoutMs, int connectionTimeoutMs, int baseSleepTimeMs, int maxEntries,
                            ExecutorService executorService) {
        this.curatorFramework = CuratorFrameworkFactory.newClient(host, sessionTimeoutMs, connectionTimeoutMs,
                new ExponentialBackoffRetry(baseSleepTimeMs, maxEntries));
        this.executorService = executorService;

        this.curatorFramework.start();
    }

    /**
     * 关闭连接
     */
    public void close() {
        this.curatorFramework.close();
    }

    /**
     * 创建节点，返回路径
     *
     * @param path
     * @return
     * @throws Exception
     */
    public String createPersistentNode(String path) throws Exception {
        return this.curatorFramework.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path);
    }

    /**
     * 异步创建节点，返回路径
     *
     * @param path
     * @return
     * @throws Exception
     */
    public String asyncCreatePersistentNode(String path) throws Exception {
        return curatorFramework.getData().inBackground((client, event) -> {
            this.curatorFramework.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path);
        }, executorService).forPath(path).toString();
    }

    /**
     * 删除节点
     *
     * @param path
     */
    public void deleteNodeIfExists(String path) throws Exception {
        if (null != curatorFramework.checkExists().forPath(path)) {
            curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
        } else {
            log.debug("节点{}不存在", path);
        }
    }

    /**
     * 判断某个节点是否存在
     * @param path
     * @return
     * @throws Exception
     */
    public boolean exists(String path) throws Exception {
        if (null != curatorFramework.checkExists().forPath(path)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 异步删除节点
     *
     * @param path
     */
    public void asyncDeleteNode(String path) throws Exception {
        curatorFramework.getData().inBackground((client, event) -> {
            curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
        }, executorService).forPath(path).toString();
    }
}
